package org.swxjava.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.xml.parsers.ParserConfigurationException;

import org.swxjava.Container;
import org.swxjava.WebContextFactory;
import org.swxjava.assembler.DefaultConverterManager;
import org.swxjava.config.SwxXmlConfigurator;
import org.swxjava.core.DefaultRemoter;
import org.swxjava.core.DefaultServiceLocatorManager;
import org.swxjava.servlet.SwxGatewayServlet.ContainerBuilder;
import org.swxjava.util.BeanUtils;
import org.swxjava.util.Log;
import org.swxjava.util.LogFactory;
import org.xml.sax.SAXException;

public class DefaultContainerBuilder implements ContainerBuilder {

	private static final Log LOG = LogFactory.getLog(DefaultContainerBuilder.class);

	private ServletConfig servletConfig;
	
	public DefaultContainerBuilder() {
	}
	
	public Container buildContainer(ServletConfig servletConfig) throws ServletException {
		this.servletConfig = servletConfig;
		try {
			// create container object
			DefaultContainer container = newInstance();

			// setup container components
			container.setConverterManager(new DefaultConverterManager());
			container.setServiceLocatorManager(new DefaultServiceLocatorManager());
			container.setWebContextBuilder(new DefaultWebContextBuilder());
			container.setRemoter(new DefaultRemoter());

			// setup WebContextFactory
			initWebContext(servletConfig, container);

			// configure the container
			configureFromSystemSwxXml(container);
			configureFromDefaultSwxXml(container);

			return container;
			
		} catch (Exception ex) {
			throw new ServletException(ex);
		}
	}

	private DefaultContainer newInstance() throws Exception {
		String containerClassName = servletConfig.getInitParameter(Container.class.getName());
		if (containerClassName != null) {
			LOG.debug("Using alternate Container implementation: " + containerClassName);
			Class type = BeanUtils.getClassForName(containerClassName);
			return (DefaultContainer) type.newInstance();
		} else {
			return new DefaultContainer();
		}
	}
	
	private void initWebContext(ServletConfig config, Container container) {
		ServletContext context = config.getServletContext();
		WebContextFactory.setWebContextBuilder(container.getWebContextBuilder());
		container.getWebContextBuilder().set(null, null, servletConfig, context, container);
	}

	public static void configureFromSystemSwxXml(Container container)
			throws IOException, ParserConfigurationException, SAXException {
		SwxXmlConfigurator system = new SwxXmlConfigurator();
		system.setClassResourceName(SwxXmlConfigurator.FILE_SWX_XML);
		system.configure(container);
	}

	public static void configureFromDefaultSwxXml(Container container)
			throws IOException, ParserConfigurationException, SAXException {
		SwxXmlConfigurator local = new SwxXmlConfigurator();
		local.setServletResourceName(SwxXmlConfigurator.DEFAULT_SWX_XML);
		local.configure(container);
	}
}
